Library

library(Rfastp)
library(qckitfastq)
library(plotly)
library(plyr)

Data

folder <- "../01_data"
files <- list.files(path = folder, pattern = ".gz", full.names = T)
names(files) <- gsub(pattern = "\\.fastq.gz", replacement = "", x = basename(files))

Rfastp

Analysis

qc_SE <- function(file, outdir, name, ad1) {
  res <- rfastp(
    read1 = file,
    outputFastq = paste(outdir, name, sep = "/"),
    thread = 4,
    cutMeanQual = 20,
    cutFrontMeanQual = 20,
    cutTailMeanQual = 20,
    cutLowQualTail = T,
    cutLowQualFront = T,
    qualityFiltering = T,
    maxNfilter = 5,
    qualityFilterPhred = 20,
    qualityFilterPercent = 40,
    lengthFiltering = T,
    minReadLength = 15,
    maxIndexMismatch = 1,
    adapterTrimming = TRUE,
    adapterSequenceRead1 = ad1
  )
  # file.remove(paste0(outdir, "/", name, ".html"))
  return(res)
}

res <- parallel::mclapply(setNames(names(files), names(files)), function(x) {
  qc_SE(file = files[[x]], outdir = "output/", name = x, ad1 = "CTGTAGGCACCATCAAT")
}, mc.preschedule = F, mc.cores = 16)

json_files <- list.files(path = "output", pattern = "json", full.names = T)
names(json_files) <- gsub(pattern = "\\.json", replacement = "", x = basename(json_files))

trim_files <- list.files(path = "output", pattern = "gz", full.names = T)
names(trim_files) <- gsub(pattern = "\\_R1.fastq.gz", replacement = "", x = basename(trim_files))

Reading and getting information from JSON file

General

#' Make general information data frame from
#'
#' @param json A JSON file with QC information
#'
#' @return A data frame with FASTQ file information
#' @export
#'
#' @examples
make_general_df <- function(json) {
  js <- rjson::fromJSON(file = json)

  # pkg <- as.character(packageVersion("Rfastp"))
  seq <- js$read1_before_filtering$total_cycles
  seq_type <- ifelse(test = any(grepl(pattern = "read2", x = names(js))), yes = "paired-end", no = "single-end")
  cycle <- paste0(seq_type, " (", seq, " cycles)")

  mean_len_bf <- js$summary$before_filtering$read1_mean_length
  mean_len_af <- js$summary$after_filtering$read1_mean_length
  dup_rate <- ifelse(test = seq_type == "paired-end",
    yes = paste0(round(x = (js$duplication$rate * 100), digits = 2), "%"),
    no = paste0(
      round(x = (js$duplication$rate * 100), digits = 2),
      "% (may be overestimated since this is SE data)"
    )
  )

  df <- data.frame(
    test = c(
      # "Rfastp version",
      "Sequencing",
      "Mean length before filtering",
      "Mean length after filtering",
      "Duplication rate"
    ),
    value = c(
      # pkg,
      cycle,
      mean_len_bf,
      mean_len_af,
      dup_rate
    )
  )
  return(df)
}

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  knitr::kable(make_general_df(json = json_files[[x]]), col.names = NULL)
}, mc.preschedule = F, mc.cores = 4)

$SRR955628

Sequencing single-end (50 cycles)
Mean length before filtering 50
Mean length after filtering 27
Duplication rate 35.69% (may be overestimated since this is SE data)

$SRR955629

Sequencing single-end (50 cycles)
Mean length before filtering 50
Mean length after filtering 27
Duplication rate 35.39% (may be overestimated since this is SE data)

$SRR955633

Sequencing single-end (50 cycles)
Mean length before filtering 50
Mean length after filtering 29
Duplication rate 45.74% (may be overestimated since this is SE data)

$SRR955634

Sequencing single-end (50 cycles)
Mean length before filtering 50
Mean length after filtering 26
Duplication rate 26.43% (may be overestimated since this is SE data)

Before QC

make_before_filt_df <- function(json) {
  js <- rjson::fromJSON(file = json)
  tot_reads <- js$read1_before_filtering$total_reads
  tot_bases <- js$read1_before_filtering$total_bases
  q_20_bases <- js$read1_before_filtering$q20_bases
  q_20_rate <- js$summary$before_filtering$q20_rate * 100
  q_30_bases <- js$read1_before_filtering$q30_bases
  q_30_rate <- js$summary$before_filtering$q30_rate * 100
  gc <- paste0(round(x = js$summary$before_filtering$gc_content * 100, digits = 2), "%")

  df <- data.frame(
    test = c(
      "Total reads",
      "Total bases",
      "Q20 bases",
      "Q30 bases",
      "GC content"
    ),
    value = c(
      tot_reads,
      tot_bases,
      paste0(q_20_bases, " (", q_20_rate, "%)"),
      paste0(q_30_bases, " (", q_30_rate, "%)"),
      gc
    )
  )
  return(df)
}


parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  knitr::kable(make_before_filt_df(json = json_files[[x]]), col.names = NULL)
}, mc.preschedule = F, mc.cores = 4)

$SRR955628

Total reads 21354015
Total bases 1067700750
Q20 bases 1035533864 (96.9873%)
Q30 bases 972278842 (91.0629%)
GC content 49.44%

$SRR955629

Total reads 15145094
Total bases 757254700
Q20 bases 732372019 (96.7141%)
Q30 bases 685909354 (90.5784%)
GC content 49.9%

$SRR955633

Total reads 18771501
Total bases 938575050
Q20 bases 910665276 (97.0264%)
Q30 bases 853893917 (90.9777%)
GC content 49.61%

$SRR955634

Total reads 8999053
Total bases 449952650
Q20 bases 433546624 (96.3538%)
Q30 bases 405844827 (90.1972%)
GC content 52.72%

After QC

make_after_filt_df <- function(json) {
  js <- rjson::fromJSON(file = json)
  tot_reads <- js$read1_after_filtering$total_reads
  tot_bases <- js$read1_after_filtering$total_bases
  q_20_bases <- js$read1_after_filtering$q20_bases
  q_20_rate <- js$summary$after_filtering$q20_rate * 100
  q_30_bases <- js$read1_after_filtering$q30_bases
  q_30_rate <- js$summary$after_filtering$q30_rate * 100
  gc <- paste0(round(x = js$summary$after_filtering$gc_content * 100, digits = 2), "%")

  df <- data.frame(
    test = c(
      "Total reads",
      "Total bases",
      "Q20 bases",
      "Q30 bases",
      "GC content"
    ),
    value = c(
      tot_reads,
      tot_bases,
      paste0(q_20_bases, " (", q_20_rate, "%)"),
      paste0(q_30_bases, " (", q_30_rate, "%)"),
      gc
    )
  )
  return(df)
}


parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  knitr::kable(make_after_filt_df(json = json_files[[x]]), col.names = NULL)
}, mc.preschedule = F, mc.cores = 4)

$SRR955628

Total reads 15818144
Total bases 438765815
Q20 bases 434345957 (98.9927%)
Q30 bases 412966207 (94.12%)
GC content 47.39%

$SRR955629

Total reads 9752048
Total bases 263972256
Q20 bases 261287984 (98.9831%)
Q30 bases 248299061 (94.0626%)
GC content 47.46%

$SRR955633

Total reads 12578898
Total bases 366313296
Q20 bases 361950551 (98.809%)
Q30 bases 342077299 (93.3838%)
GC content 47.02%

$SRR955634

Total reads 1746985
Total bases 45581788
Q20 bases 45018894 (98.7651%)
Q30 bases 42379168 (92.9739%)
GC content 49.5%

Filtering result

make_filt_df <- function(json) {
  js <- rjson::fromJSON(file = json)

  reads <- js$summary$before_filtering$total_reads
  read_pass <- js$filtering_result$passed_filter_reads
  read_pass_pct <- round((read_pass / reads) * 100, 2)
  read_low_Q <- js$filtering_result$low_quality_reads
  read_low_Q_pct <- round((read_low_Q / reads) * 100, 2)
  read_with_N <- js$filtering_result$too_many_N_reads
  read_with_N_pct <- round((read_with_N / reads) * 100, 2)
  read_short <- js$filtering_result$too_short_reads
  read_short_pct <- round((read_short / reads) * 100, 2)
  read_long <- js$filtering_result$too_long_reads
  read_long_pct <- round((read_pass / reads) * 100, 2)

  df <- data.frame(
    test = c(
      "Reads passed filters",
      "Reads with low quality",
      "Reads with too many N",
      "Reads too short",
      "Reads too long"
    ),
    value = c(
      paste0(read_pass, " (", read_pass_pct, "%)"),
      paste0(read_low_Q, " (", read_low_Q_pct, "%)"),
      paste0(read_with_N, " (", read_with_N_pct, "%)"),
      paste0(read_short, " (", read_short_pct, "%)"),
      paste0(read_long, " (", read_long_pct, "%)")
    )
  )
  return(df)
}


parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  knitr::kable(make_filt_df(json = json_files[[x]]), col.names = NULL)
}, mc.preschedule = F, mc.cores = 4)

$SRR955628

Reads passed filters 15818144 (74.08%)
Reads with low quality 12166 (0.06%)
Reads with too many N 0 (0%)
Reads too short 5523705 (25.87%)
Reads too long 0 (74.08%)

$SRR955629

Reads passed filters 9752048 (64.39%)
Reads with low quality 9227 (0.06%)
Reads with too many N 0 (0%)
Reads too short 5383819 (35.55%)
Reads too long 0 (64.39%)

$SRR955633

Reads passed filters 12578898 (67.01%)
Reads with low quality 11657 (0.06%)
Reads with too many N 0 (0%)
Reads too short 6180946 (32.93%)
Reads too long 0 (67.01%)

$SRR955634

Reads passed filters 1746985 (19.41%)
Reads with low quality 3238 (0.04%)
Reads with too many N 0 (0%)
Reads too short 7248830 (80.55%)
Reads too long 0 (19.41%)

Duplicated reads plot

make_dup_plot <- function(json) {
  js <- rjson::fromJSON(file = json)

  bars <- js$duplication$histogram
  gc <- js$duplication$mean_gc
  xaxis <- 1:length(bars)

  data <- data.frame(
    Duplicate = round(bars / sum(bars) * 100, 2),
    GC = round(gc * 100, 2),
    x = xaxis
  )
  data$GC[data$GC == 0] <- ""

  p <- plot_ly(data, x = ~x) %>%
    add_trace(
      y = ~Duplicate,
      type = "bar",
      name = "Read percent",
      hoverinfo = "text+x",
      hovertext = paste(
        "<b>", data$Duplicate, "</b>"
      )
    ) %>%
    add_lines(
      y = ~GC,
      name = "Mean GC ratio (%)",
      line = list(color = "red", width = 3),
      hoverinfo = "text+x",
      hovertext = paste(
        "<b>", data$GC, "</b>"
      )
    ) %>%
    layout(
      title = paste0("Duplication rate: ", round(js$duplication$rate * 100, 2), "%"),
      xaxis = list(title = "Duplication level"),
      yaxis = list(title = "Reads percent & GC ratio (%)"),
      hovermode = "x closest"
    )
  print(htmltools::tagList(p))
}

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_dup_plot(json = json_files[[x]])
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

Read quality plot

make_read_qual_plot <- function(json, which = "before") {
  js <- rjson::fromJSON(file = json)

  qual <- NULL
  if (which == "before") {
    qual <- js$read1_before_filtering$quality_curves
  } else {
    qual <- js$read1_after_filtering$quality_curves
  }

  data <- data.frame(
    pos = 1:length(qual$mean),
    Aa = qual$A,
    Tt = qual$T,
    Gg = qual$G,
    Cc = qual$C,
    Mm = qual$mean
  )

  data$Q20 <- 20
  data$Q28 <- 8
  data$Q50 <- 18

  cols <- rcartocolor::carto_pal(n = 10, name = "Safe")[c(2, 1, 3, 4, 10)]

  p <- plot_ly(data, x = ~pos) %>%
    add_trace(
      y = ~Q20, name = "Not good", fillcolor = "rgba(255,0,0, 0.2)", type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_trace(
      y = ~Q28, name = "OK", fillcolor = "rgba(255,255,0,0.2)", type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_trace(
      y = ~Q50, name = "Good", fillcolor = "rgba(0,128,0,0.2)", type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_lines(
      y = ~Aa,
      name = "A",
      line = list(color = cols[1], width = 2),
      hoverinfo = "text",
      hovertext = paste("<b>", data$Aa, "</b>")
    ) %>%
    add_lines(
      y = ~Tt,
      name = "T",
      line = list(color = cols[2], width = 2),
      hoverinfo = "text",
      hovertext = paste("<b>", data$Tt, "</b>")
    ) %>%
    add_lines(
      y = ~Gg,
      name = "G",
      line = list(color = cols[3], width = 2),
      hoverinfo = "text",
      hovertext = paste("<b>", data$Gg, "</b>")
    ) %>%
    add_lines(
      y = ~Cc,
      name = "C",
      line = list(color = cols[4], width = 2),
      hoverinfo = "text",
      hovertext = paste("<b>", data$Cc, "</b>")
    ) %>%
    add_lines(
      y = ~Mm,
      name = "Mean",
      line = list(color = "black", width = 3, dash = "dot"),
      hoverinfo = "text",
      hovertext = paste("<b>", data$Mm, "</b>")
    ) %>%
    layout(
      title = "Per base sequence quality",
      xaxis = list(title = "Position in read (bp)"),
      yaxis = list(title = "Quality score"),
      hovermode = "x closest"
    )

  print(htmltools::tagList(p))
}

Before QC

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_read_qual_plot(json = json_files[[x]], which = "before")
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

After QC

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_read_qual_plot(json = json_files[[x]], which = "after")
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

Base content line plot

make_base_ratio_line_plot <- function(json, which = "before") {
  js <- rjson::fromJSON(file = json)

  qual <- NULL
  if (which == "before") {
    qual <- js$read1_before_filtering$content_curves
  } else {
    qual <- js$read1_after_filtering$content_curves
  }

  data <- data.frame(
    pos = 1:length(qual$A),
    Aa = qual$A * 100,
    Tt = qual$T * 100,
    Gg = qual$G * 100,
    Cc = qual$C * 100,
    GC = qual$GC * 100,
    Nn = qual$N * 100
  )

  cols <- rcartocolor::carto_pal(n = 11, name = "Safe")[c(2, 1, 3, 4, 10)]

  p <- plot_ly(data, x = ~pos) %>%
    add_lines(
      y = ~Aa,
      name = "A",
      line = list(color = cols[1], width = 2),
      hoverinfo = "text+x",
      hovertext = paste("<b>", data$Aa, "</b>")
    ) %>%
    add_lines(
      y = ~Tt,
      name = "T",
      line = list(color = cols[2], width = 2),
      hoverinfo = "text+x",
      hovertext = paste("<b>", data$Tt, "</b>")
    ) %>%
    add_lines(
      y = ~Gg,
      name = "G",
      line = list(color = cols[3], width = 2),
      hoverinfo = "text+x",
      hovertext = paste("<b>", data$Gg, "</b>")
    ) %>%
    add_lines(
      y = ~Cc,
      name = "C",
      line = list(color = cols[4], width = 2),
      hoverinfo = "text+x",
      hovertext = paste("<b>", data$Cc, "</b>")
    ) %>%
    add_lines(
      y = ~GC,
      name = "GC",
      line = list(color = cols[5], width = 3, dash = "dot"),
      hoverinfo = "text+x",
      hovertext = paste("<b>", data$GC, "</b>")
    ) %>%
    add_lines(
      y = ~Nn,
      name = "N",
      line = list(color = "black", width = 3),
      hoverinfo = "text+x",
      hovertext = paste("<b>", data$Nn, "</b>")
    ) %>%
    layout(
      title = "Per base sequence content",
      xaxis = list(title = "Position in read (bp)/ Cycle"),
      yaxis = list(title = "Percentage (%)"),
      hovermode = "x closest"
    )
  print(htmltools::tagList(p))
}

Before QC

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_base_ratio_line_plot(json = json_files[[x]], which = "before")
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

After QC

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_base_ratio_line_plot(json = json_files[[x]], which = "after")
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

Base content ratio proportion plot

make_base_ratio_prop_plot <- function(json, which = "before") {
  js <- rjson::fromJSON(file = json)

  qual <- NULL
  if (which == "before") {
    qual <- js$read1_before_filtering$content_curves
  } else {
    qual <- js$read1_after_filtering$content_curves
  }

  data <- data.frame(
    pos = 1:length(qual$A),
    Aa = qual$A * 100,
    Tt = qual$T * 100,
    Gg = qual$G * 100,
    Cc = qual$C * 100,
    GC = qual$GC * 100,
    Nn = qual$N * 100
  )

  cols <- rcartocolor::carto_pal(n = 11, name = "Safe")[c(2, 1, 3, 4, 10)]

  p <- plot_ly(data, x = ~pos) %>%
    add_trace(
      y = ~Nn, name = "N", fillcolor = "black", type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_trace(
      y = ~Cc, name = "C", fillcolor = cols[4], type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_trace(
      y = ~Gg, name = "G", fillcolor = cols[3], type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_trace(
      y = ~Tt, name = "T", fillcolor = cols[2], type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_trace(
      y = ~Aa, name = "A", fillcolor = cols[1], type = "scatter",
      mode = "none", stackgroup = "one", hoverinfo = "skip"
    ) %>%
    add_lines(
      y = ~GC,
      name = "GC",
      line = list(color = cols[5], width = 3, dash = "dot"),
      hoverinfo = "text",
      hovertext = paste("<b>", data$GC, "</b>")
    ) %>%
    layout(
      title = "Per base sequence content",
      xaxis = list(title = "Position in read (bp)/ Cycle"),
      yaxis = list(title = "Percentage (%)"),
      hovermode = "x closest"
    )
  print(htmltools::tagList(p))
}

Before QC

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_base_ratio_prop_plot(json = json_files[[x]], which = "before")
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

After QC

parallel::mclapply(setNames(names(json_files), names(json_files)), function(x) {
  make_base_ratio_prop_plot(json = json_files[[x]], which = "after")
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

qckitfastq

Analysis

run_qc <- function(fq) {
  out <- list()

  infile <- fq
  fseq <- seqTools::fastqq(infile)

  ## Read length
  read_len <- read_length(fseq)
  # plot_read_length(read_len)

  ## Per base sequence quality
  bs <- per_base_quality(infile)
  # plot_per_base_quality(bs)

  ## Per read quality
  prq <- per_read_quality(infile)
  # plot_per_read_quality(prq)

  ## GC content
  gc_df <- GC_content(infile)
  # plot_GC_content(gc_df)

  ## Nucleotide read content
  rc <- read_content(fseq)
  # plot_read_content(rc)

  ## Kmer count
  km <- kmer_count(infile, k = 6)

  ## Overrep reads
  # overrep_reads <- overrep_reads(infile)
  # plot_overrep_reads(overrep_reads)

  ## Overrep kmer
  overkm <- overrep_kmer(infile, 7)
  # plot_overrep_kmer(overkm)

  ## Adapter content
  if (.Platform$OS.type != "windows") {
    ac_sorted <- adapter_content(infile)
    # plot_adapter_content(ac_sorted)
  } else {
    ac_sorted <- "adapter_content not available for Windows; skipping"
    print("adapter_content not available for Windows; skipping")
  }

  out <- list(
    read_length = read_len,
    per_base_quality = bs,
    per_read_quality = prq,
    GC_content = gc_df,
    read_content = rc,
    kmer_count = km,
    overrep_kmer = overkm,
    overrep_reads = overrep_reads,
    adapter_content = ac_sorted
  )
  return(out)
}


res1 <- parallel::mclapply(setNames(names(files), names(files)), function(x) {
  run_qc(fq = files[[x]])
}, mc.preschedule = F, mc.cores = 4)


res2 <- parallel::mclapply(setNames(names(trim_files), names(trim_files)), function(x) {
  run_qc(fq = trim_files[[x]])
}, mc.preschedule = F, mc.cores = 4)

Read length distribution

#' Read length distribution plot
#'
#' @param before_trim A dataframe with 2 columns: read_length and num_reads
#' @param after_trim A dataframe with 2 columns: read_length and num_reads
#'
#' @return An interactive barplot
#' @export
#'
#' @examples
read_length_plot <- function(before_trim, after_trim) {
  if (!colnames(before_trim) %in% c("read_length", "num_reads") |
    !colnames(after_trim) %in% c("read_length", "num_reads")) {
    message("Please check the columns of input")
  }
  raw <- before_trim
  trim <- after_trim
  raw$Group <- "Raw"
  trim$Group <- "Trimmed"

  p1 <- plot_ly(hoverinfo = "text", type = "bar", textposition = "auto") %>%
    add_trace(
      data = raw,
      legendgroup = ~Group,
      x = ~read_length, y = ~num_reads,
      name = ~Group,
      # text = ~`%Reads`,
      marker = list(color = "red"),
      hovertext = paste(
        "<b>Length:</b> ", raw$read_length,
        "<br><b>nReads:</b> ", raw$num_reads
        # , "<br><b>%Reads:</b> ", t$`%Reads`
      )
    ) %>%
    layout(
      title = "Histogram of read length distribution",
      xaxis = list(title = "Reads length"),
      yaxis = list(title = "No. of reads"),
      hovermode = "x closest"
    )

  p2 <- plot_ly(hoverinfo = "text", type = "bar", textposition = "auto") %>%
    add_trace(
      data = trim,
      legendgroup = ~Group,
      x = ~read_length, y = ~num_reads,
      name = ~Group,
      # text = ~`%Reads`,
      marker = list(color = "green"),
      hovertext = paste(
        "<b>Length:</b> ", trim$read_length,
        "<br><b>nReads:</b> ", trim$num_reads
        # , "<br><b>%Reads:</b> ", t$`%Reads`
      )
    ) %>%
    layout(
      title = "Histogram of read length distribution",
      xaxis = list(title = "Reads length"),
      yaxis = list(title = "No. of reads"),
      hovermode = "x closest"
    )
  p <- subplot(p1, p2, shareX = T, shareY = T)
  print(htmltools::tagList(p))
}

parallel::mclapply(setNames(names(res1), names(res1)), function(x) {
  read_length_plot(before_trim = res1[[x]]$read_length, after_trim = res2[[x]]$read_length)
}, mc.preschedule = F, mc.cores = 4)
$SRR955628
$SRR955629
$SRR955633
$SRR955634

References

report::cite_packages(session = sessionInfo())

SessionInfo

devtools::session_info() %>%
  details::details()

─ Session info ───────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 4.0.4 (2021-02-15)
 os       Ubuntu 16.04.7 LTS          
 system   x86_64, linux-gnu           
 ui       X11                         
 language (EN)                        
 collate  en_US.UTF-8                 
 ctype    en_US.UTF-8                 
 tz       Europe/Zurich               
 date     2021-05-17                  

─ Packages ───────────────────────────────────────────────────────────────────
 package     * version date       lib
 assertthat    0.2.1   2019-03-21 [1]
 bslib         0.2.4   2021-01-25 [1]
 cachem        1.0.4   2021-02-13 [1]
 callr         3.7.0   2021-04-20 [1]
 cli           2.5.0   2021-04-26 [1]
 clipr         0.7.1   2020-10-08 [1]
 colorspace    2.0-0   2020-11-11 [1]
 crayon        1.4.1   2021-02-08 [1]
 crosstalk     1.1.1   2021-01-12 [1]
 data.table    1.14.0  2021-02-21 [1]
 DBI           1.1.1   2021-01-15 [1]
 desc          1.3.0   2021-03-05 [1]
 details       0.2.1   2020-01-12 [1]
 devtools      2.4.0   2021-04-07 [1]
 digest        0.6.27  2020-10-24 [1]
 dplyr         1.0.5   2021-03-05 [1]
 ellipsis      0.3.1   2020-05-15 [1]
 evaluate      0.14    2019-05-28 [1]
 fansi         0.4.2   2021-01-15 [1]
 fastmap       1.1.0   2021-01-25 [1]
 fs            1.5.0   2020-07-31 [1]
 generics      0.1.0   2020-10-31 [1]
 ggplot2     * 3.3.3   2020-12-30 [1]
 glue          1.4.2   2020-08-27 [1]
 gtable        0.3.0   2019-03-25 [1]
 htmltools     0.5.1.1 2021-01-22 [1]
 htmlwidgets   1.5.3   2020-12-10 [1]
 httr          1.4.2   2020-07-20 [1]
 jquerylib     0.1.4   2021-04-26 [1]
 jsonlite      1.7.2   2020-12-09 [1]
 knitr         1.33    2021-04-24 [1]
 lazyeval      0.2.2   2019-03-15 [1]
 lifecycle     1.0.0   2021-02-15 [1]
 magrittr      2.0.1   2020-11-17 [1]
 memoise       2.0.0   2021-01-26 [1]
 munsell       0.5.0   2018-06-12 [1]
 pillar        1.6.0   2021-04-13 [1]
 pkgbuild      1.2.0   2020-12-15 [1]
 pkgconfig     2.0.3   2019-09-22 [1]
 pkgload       1.2.1   2021-04-06 [1]
 plotly      * 4.9.3   2021-01-10 [1]
 plyr        * 1.8.6   2020-03-03 [1]
 png           0.1-7   2013-12-03 [1]
 prettyunits   1.1.1   2020-01-24 [1]
 processx      3.5.1   2021-04-04 [1]
 ps            1.6.0   2021-02-28 [1]
 purrr         0.3.4   2020-04-17 [1]
 qckitfastq  * 1.6.0   2020-10-27 [1]
 R6            2.5.0   2020-10-28 [1]
 Rcpp          1.0.6   2021-01-15 [1]
 remotes       2.3.0   2021-04-01 [1]
 reshape2      1.4.4   2020-04-09 [1]
 Rfastp      * 0.99.6  2021-05-06 [1]
 rjson         0.2.20  2018-06-08 [1]
 rlang         0.4.10  2020-12-30 [1]
 rmarkdown     2.7     2021-02-19 [1]
 rprojroot     2.0.2   2020-11-15 [1]
 RSeqAn        1.10.0  2020-10-27 [1]
 sass          0.3.1   2021-01-24 [1]
 scales        1.1.1   2020-05-11 [1]
 sessioninfo   1.1.1   2018-11-05 [1]
 stringi       1.5.3   2020-09-09 [1]
 stringr       1.4.0   2019-02-10 [1]
 testthat      3.0.2   2021-02-14 [1]
 tibble        3.1.1   2021-04-18 [1]
 tidyr         1.1.3   2021-03-03 [1]
 tidyselect    1.1.0   2020-05-11 [1]
 usethis       2.0.1   2021-02-10 [1]
 utf8          1.2.1   2021-03-12 [1]
 vctrs         0.3.7   2021-03-29 [1]
 viridisLite   0.4.0   2021-04-13 [1]
 withr         2.4.2   2021-04-18 [1]
 xfun          0.22    2021-03-11 [1]
 xml2          1.3.2   2020-04-23 [1]
 yaml          2.2.1   2020-02-01 [1]
 zlibbioc      1.36.0  2020-10-27 [1]
 source                                       
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 Bioconductor                                 
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 Github (RockefellerUniversity/Rfastp@59a1d4f)
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 Bioconductor                                 
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 CRAN (R 4.0.4)                               
 Bioconductor                                 

[1] /home/ubuntu/R/x86_64-pc-linux-gnu-library/4.0
[2] /usr/local/lib/R/site-library
[3] /usr/lib/R/site-library
[4] /usr/lib/R/library